package cn.iocoder.ny.module.activity.service.impl;

import cn.iocoder.ny.module.activity.controller.admin.login.vo.TpLoginVo;
import cn.iocoder.ny.module.activity.domain.Activity;
import cn.iocoder.ny.module.activity.service.IActivityService;
import cn.iocoder.ny.module.activity.service.ITpLoginService;
import cn.iocoder.yudao.module.system.constant.WeChatAppConstants;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.activity.ActivityUser;
import cn.iocoder.yudao.module.system.dal.dataobject.system.SystemUsers;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.dal.mysql.activity.ActivityUserMapper;
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
import cn.iocoder.yudao.module.system.service.activity.ActivityService;
import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
import cn.iocoder.yudao.module.system.service.auth.AdminAuthServiceImpl;
import cn.iocoder.yudao.module.system.service.system.ISystemUserService;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import cn.iocoder.yudao.module.system.util.OkHttpUtils;
import com.alibaba.fastjson2.JSON;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.AbstractCollection;
import java.util.Map;

/**
 * @author luchunhong
 * @date 2024/11/19/ 15:19
 * @description:
 */
@Service
public class ITpLoginServiceImpl implements ITpLoginService {

    @Resource
    private ISystemUserService systemUserService;
    @Resource
    private ActivityService activityUserService;
    @Resource
    private IActivityService activityService;
    @Resource
    private AdminAuthServiceImpl adminAuthService;
    @Resource
    private TenantService tenantService;


    /**
     * 投票微信授权获取头昵称登录
     * @param tpLoginVo
     * @return
     * @throws Exception
     */
    @Override
    public AuthLoginRespVO wxLogin(TpLoginVo tpLoginVo) throws Exception {
        Long activityId = tpLoginVo.getActivityId();
        Activity activityInfo = activityService.lambdaQuery().eq(Activity::getId, activityId).eq(Activity::getDeleted, 0).one();

        if (ObjectUtils.isEmpty(activityInfo)) {
            throw new RuntimeException("活动配置出错,请联系管理员");
        }

        String wxOpenId = getWxOpenId("wx59d2c278e4e88df1", "5262c2e0bc422ccb7290fcf5f26e3915", tpLoginVo.getCode());
        SystemUsers systemUserInfo = systemUserService.lambdaQuery().eq(SystemUsers::getOpenId, wxOpenId).eq(SystemUsers::getTenantId, activityInfo.getTenantId()).one();
        TenantDO tenant = tenantService.getTenant(activityInfo.getTenantId());

        if (!ObjectUtils.isEmpty(systemUserInfo)) {
            ActivityUser activityUserInfo = activityUserService.lambdaQuery().eq(ActivityUser::getOpenId, wxOpenId).eq(ActivityUser::getActivityId, activityId)
                    .eq(ActivityUser::getUserId, systemUserInfo.getId()).one();

           // 若在activityUser表内查询到该用户，直接返回token,若查不到该用户则先新增再返回token
            if (!ObjectUtils.isEmpty(activityUserInfo) || addUserToActivityUser(wxOpenId, systemUserInfo.getId(), activityId, activityInfo.getTenantId())) {
                AuthLoginRespVO tokenAfterLoginSuccess = adminAuthService.createTokenAfterLoginSuccessByActivityId(systemUserInfo.getId(), systemUserInfo.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL,activityId);
                tokenAfterLoginSuccess.setTenantId(activityInfo.getTenantId());
                tokenAfterLoginSuccess.setTenantName(tenant.getName());
                return tokenAfterLoginSuccess;
            }
        }
        // 若该用户是第一次进入该店铺
            systemUserInfo = new SystemUsers();
            systemUserInfo.setOpenId(wxOpenId);
            systemUserInfo.setNickname(tpLoginVo.getNickname());
            systemUserInfo.setUsername(tpLoginVo.getOpenId());
            systemUserInfo.setAvatar(tpLoginVo.getAvatar());
            systemUserInfo.setTenantId(activityInfo.getTenantId());
            systemUserService.save(systemUserInfo);

            if (addUserToActivityUser(wxOpenId, systemUserInfo.getId(), activityId, activityInfo.getTenantId())) {
                AuthLoginRespVO tokenAfterLoginSuccess = adminAuthService.createTokenAfterLoginSuccessByActivityId(systemUserInfo.getId(), systemUserInfo.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL,activityId);
                tokenAfterLoginSuccess.setTenantId(activityInfo.getTenantId());
                tokenAfterLoginSuccess.setTenantName(tenant.getName());
                return tokenAfterLoginSuccess;
            }
        throw new RuntimeException("活动配置出错,请联系管理员");
    }

    private Boolean addUserToActivityUser(String wxOpenId, Long userId, Long activityId, Long tenantId) {
        ActivityUser activityUser = new ActivityUser();
        activityUser.setUserId(userId);
        activityUser.setTenantId(tenantId);
        activityUser.setRole("tp_common");
        activityUser.setOpenId(wxOpenId);
        activityUser.setAppId("wx59d2c278e4e88df1");
        activityUser.setActivityId(activityId);
        return activityUserService.save(activityUser);
    }


    private String getWxOpenId(String appid,String secret,String code) throws Exception {
        //微信登录方法,请求接口https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
        String message = OkHttpUtils.builder().url(WeChatAppConstants.LOGINURL)
                // 有参数的话添加参数，可多个
                .addParam("appid", appid)
                .addParam("secret", secret)
                .addParam("js_code", code)
                .addParam("grant_type", "authorization_code")
                //.addHeader("Content-Type", "application/json; charset=utf-8")
                .get()
                // 可选择是同步请求还是异步请求
                .async();
        // .sync();
        //message转map
        Map<String, Object> map = JSON.parseObject(message, Map.class);
        String openid = String.valueOf(map.get("openid"));
        if (null==openid){
            throw  new Exception("小程序登录失败，请联系管理员");
        }
        return openid;
    }
}
